#include "../main.h"

typedef struct Node
{
    int number;
    struct Node* next;
}Node;

sem_t producer_sem;
sem_t consumer_sem;

pthread_mutex_t mutex;
Node* head=NULL;

void* producer(void* arg);
void* consumer(void* arg);

#define PRODUCER_NUMBER 5
#define CONSUMER_NUMBER 5

int main()
{
    sem_init(&producer_sem,0,10);
    sem_init(&consumer_sem,0,0);
    
    pthread_mutex_init(&mutex,NULL);
    
    pthread_t producer_id[PRODUCER_NUMBER];
    pthread_t consumer_id[CONSUMER_NUMBER];

    for(int i=0;i<PRODUCER_NUMBER;i++)
    {
        pthread_create(producer_id+i,NULL,producer,NULL);
    }

    for(int i=0;i<CONSUMER_NUMBER;i++)
    {
        pthread_create(consumer_id+i,NULL,consumer,NULL);
    }
    
    for(int i=0;i<PRODUCER_NUMBER;i++)
    {
        pthread_join(producer_id[i],NULL);
    }

    for(int i=0;i<CONSUMER_NUMBER;i++)
    {
        pthread_join(consumer_id[i],NULL);
    }
    
    sem_destroy(&producer_sem);
    sem_destroy(&consumer_sem);
    pthread_mutex_destroy(&mutex);
    return 0;
}

void* producer(void* arg)
{
    while(1)
    {
        sem_wait(&producer_sem);
        pthread_mutex_lock(&mutex);
        Node* node=(Node*)calloc(1,sizeof(Node));
        node->next=head;
        node->number=rand()%1000;
        head=node;
        int val=0;
        sem_getvalue(&producer_sem,&val);
        printf("+++producer, number = %d, tid = %ld  val = %d\n", node->number, pthread_self(),val);
        pthread_mutex_unlock(&mutex);
        sem_post(&consumer_sem);
        sleep(rand()%3);
    }
    return NULL;
}

void* consumer(void* arg)
{
    while(1)
    {
        sem_wait(&consumer_sem);
        pthread_mutex_lock(&mutex);
        Node* node=head;
        head=node->next;
        printf("---consumer, number = %d, tid = %ld\n", node->number, pthread_self());
        free(node);
        pthread_mutex_unlock(&mutex);
        sem_post(&producer_sem);
        sleep(rand()%3);
    }
    return NULL;
}
